Skip to content

fix(server): thread.turn.start bootstrap parity between websocket and http dispatch - #7996

Open
pablospe wants to merge 6 commits into
pingdotgg:mainfrom
pablospe:orc/http-bootstrap-parity
Open

fix(server): thread.turn.start bootstrap parity between websocket and http dispatch#7996
pablospe wants to merge 6 commits into
pingdotgg:mainfrom
pablospe:orc/http-bootstrap-parity

Conversation

@pablospe

@pablospe pablospe commented Aug 23, 2026

Copy link
Copy Markdown

What Changed

The thread-bootstrap flow that thread.turn.start can carry (bootstrap: create thread → prepare git worktree → run project setup script → start the turn, with rollback via thread.delete on failure) moves verbatim out of ws.ts into a shared TurnStartBootstrap service (apps/server/src/orchestration/TurnStartBootstrap.ts). Both transports now use it:

  • ws.ts calls the service with its client origin, exactly as before; ~300 duplicated lines removed.
  • orchestration/http.ts branches to the service when a thread.turn.start carries bootstrap. A bootstrap that fails after creating its thread (and rolls it back) now surfaces over HTTP as its own reason, orchestration_bootstrap_rolled_back — the HTTP equivalent of the WebSocket error's bootstrapThreadDisposition: "deleted" — so a caller knows not to reuse the thread id.
  • server.ts provides the layer; bin.test.ts gets a mock layer.

Tests (vp test run apps/server/src/server.test.ts): HTTP bootstrap success asserts the command sequence thread.create → thread.meta.update → thread.turn.start with bootstrap stripped from the final command and the worktree path propagated; failure asserts the rollback thread.create → thread.delete and the rolled-back reason. Existing WebSocket bootstrap tests untouched and green.

Most of the diff is the moved block; net-new logic is the ~25-line HTTP branch and wiring.

Why

POST /api/orchestration/dispatch accepts the ClientOrchestrationCommand union, whose thread.turn.start includes the optional bootstrap field — but only the WebSocket path ran the bootstrap steps. Over HTTP the same command reached the engine untouched and failed with OrchestrationCommandInvariantError: Thread does not exist: the endpoint advertised a shape it broke on.

This matters for anything driving a T3 server over HTTP (scripts, orchestrators): they had to reimplement bootstrap client-side — shelling git worktree add locally (same-machine only), hardcoding the worktree layout, and skipping the project setup script entirely. Moving the existing flow behind a shared service is transport parity, not new capability: the identical bearer auth already triggered this exact flow over WebSocket.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes (no UI changes)
  • I included a video for animation/interaction changes (not applicable)

Note

Medium Risk
Touches command dispatch, git worktree creation, and thread rollback on both transports. Behavior is extracted rather than rewritten, but HTTP callers now trigger that path.

Overview
HTTP POST /api/orchestration/dispatch now runs the same thread.turn.start bootstrap as WebSocket: create thread, prepare worktree, optional setup script, then start the turn. Previously HTTP forwarded bootstrap to the engine and failed because the thread did not exist.

The flow is extracted from ws.ts into a shared TurnStartBootstrap service. WebSocket still passes client origin on sub-commands; HTTP does not. If bootstrap fails after thread.create, rollback still deletes the thread. HTTP surfaces that as orchestration_bootstrap_rolled_back so callers must not reuse the thread id.

Tests cover HTTP success (thread.createthread.meta.update → stripped thread.turn.start) and rollback (thread.createthread.delete).

Reviewed by Cursor Bugbot for commit 9dd69ae. Bugbot is set up for automated code reviews on this repo. Configure here.

POST /api/orchestration/dispatch passed commands straight to the
orchestration engine, skipping the bootstrap steps the WebSocket path
runs for a thread.turn.start carrying `bootstrap`. An HTTP turn start for
a not-yet-existing thread therefore failed with "Thread does not exist"
even though the contract advertises bootstrap on that endpoint.

The bootstrap flow (thread.create, worktree preparation, setup script,
rollback via thread.delete on failure) now lives in a shared
TurnStartBootstrap service that both the WebSocket RPC and the HTTP
dispatch route use. The ws path keeps its client-origin stamping and
command gating; HTTP gains the bootstrap branch. Tests cover HTTP
bootstrap success and rollback alongside the existing ws cases.
@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XL 500-999 changed lines (additions + deletions). labels Aug 23, 2026
@coderabbitai

coderabbitai Bot commented Aug 23, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3230932b-b64a-46ef-a584-f26caec4cd34

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment thread apps/server/src/orchestration/TurnStartBootstrap.ts
Comment thread apps/server/src/orchestration/TurnStartBootstrap.ts

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the new TurnStartBootstrap service and its call sites against the Effect service conventions. Service definition (namespace imports, inline Context.Service interface, make + layer, dependencies acquired via yield*), layer wiring in server.ts/ws.ts, and the HTTP dispatch path all look correct. One change-discipline issue on the moved helper is noted inline.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/orchestration/TurnStartBootstrap.ts
@macroscopeapp

macroscopeapp Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This change enables HTTP callers to create threads, prepare worktrees, launch setup scripts, and start turns through a new shared bootstrap workflow, with rollback and new error signaling. Its cross-transport orchestration and substantial side effects exceed a small, isolated fix and merit human review.

You can add or adjust custom eligibility rules. Learn more.

The move dropped the original never-typed default branch, so a new
ProjectSetupScriptRunnerError tag would silently stringify into a
user-visible activity payload instead of failing the build. Restored
verbatim from the pre-move ws.ts helper.
@pablospe pablospe changed the title fix(server): http dispatch honors turn.start bootstrap fix(server): thread.turn.start bootstrap parity between websocket and http dispatch Aug 23, 2026
The comment stayed behind in ws.ts above an unrelated function when the
helper moved into TurnStartBootstrap.
Over WebSocket a failed bootstrap returns bootstrapThreadDisposition
"deleted" so the client knows the thread is gone; the HTTP branch
collapsed every failure into orchestration_dispatch_failed. It now maps
that case to its own reason, orchestration_bootstrap_rolled_back, so an
HTTP caller can retry with a fresh thread id instead of guessing. The
origin-threading comment also stops claiming HTTP callers stamp one.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL 500-999 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant